<?php
class AgoraController
{
    const appID = '130c86cae59d49f2bc40df87d9906b88';
    const appCertificate = '18a302ebbc6843e084ee2b556a914610';
    
    const AgoraVersion = "005";
    // InChannelPermissionKey
    const ALLOW_UPLOAD_IN_CHANNEL = 1;
    
    // Service Type
    const MEDIA_CHANNEL_SERVICE = 1;
    const RECORDING_SERVICE = 2;
    const PUBLIC_SHARING_SERVICE = 3;
    const IN_CHANNEL_PERMISSION = 4;
    
    public function index()
    {
        $this->display();
    }
    
    /**
    * $appID           App ID          https://dashboard.agora.io/projects wuyifan
    * $appCertificate  App Certificate https://dashboard.agora.io/projects wuyifan
    * $channelName     频道名称 agora云端会检测该频道是否存在，不存在则创建
    * $ts              当前时间戳
    * $randomInt       随机数
    * $uid             用户唯一uid
    * $expiredTs       限制用户使用当前服务的时间 如果对终止时间没有限制，设置为 0
    */
    public function generateKey($channelName, $uid, $fun)
    {
        switch ($fun)
        {
            case 'generateRecordingKey':
                $void = $this->generateDynamicKey($channelName, $uid, self::RECORDING_SERVICE, array());                
                break;
            case 'generateMediaChannelKey':
                $void = $this->generateDynamicKey($channelName, $uid, self::MEDIA_CHANNEL_SERVICE, array());
                break;
            case 'generateInChannelPermissionKey':
                $extra[self::ALLOW_UPLOAD_IN_CHANNEL] = $permission;
                $void = $this->generateDynamicKey($channelName, $uid, self::IN_CHANNEL_PERMISSION, $extra);
                break;
        }
        
        return $void;
    }

    protected function generateDynamicKey($channelName, $uid, $serviceType, $extra)
    {
        //$ts = $_SERVER["REQUEST_TIME"];
        $ts = time();
        $randomInt = rand(11111111,99999999);
        $expiredTs = 0;        
        $signature = $this->generateSignature($serviceType, $channelName, $uid, $ts, $randomInt, $expiredTs, $extra);        
        $content = $this->packContent($serviceType, $signature, $ts, $randomInt, $expiredTs, $extra);
        return self::AgoraVersion. base64_encode($content);
    }

    /***********agora密钥算法*************/
    private function generateSignature($serviceType, $channelName, $uid, $ts, $salt, $expiredTs, $extra)
    {
        $rawAppID = hex2bin(self::appID);
        $rawAppCertificate = hex2bin(self::appCertificate);
        
        $buffer = pack("S", $serviceType);
        $buffer .= pack("S", strlen($rawAppID)) . $rawAppID;
        $buffer .= pack("I", $ts);
        $buffer .= pack("I", $salt);
        $buffer .= pack("S", strlen($channelName)) . $channelName;
        $buffer .= pack("I", $uid);
        $buffer .= pack("I", $expiredTs);

        $buffer .= pack("S", count($extra));
        foreach ($extra as $key => $value) {
            $buffer .= pack("S", $key);
            $buffer .= pack("S", strlen($value)) . $value;
        } 

        return strtoupper(hash_hmac('sha1', $buffer, $rawAppCertificate));
    }
    private function packString($value)
    {
        return pack("S", strlen($value)) . $value;
    }
    private function packContent($serviceType, $signature, $ts, $salt, $expiredTs, $extra)
    {
        $buffer = pack("S", $serviceType);
        $buffer .= $this->packString($signature);
        $buffer .= $this->packString(hex2bin(self::appID));
        $buffer .= pack("I", $ts);
        $buffer .= pack("I", $salt);
        $buffer .= pack("I", $expiredTs);

        $buffer .= pack("S", count($extra));
        foreach ($extra as $key => $value) {
            $buffer .= pack("S", $key);
            $buffer .= $this->packString($value);
        } 

        return $buffer;
    }
}